﻿''' <summary> 
''' Summary description for FileUploadProcess 
''' </summary>
Public Delegate Sub FileUploadCompletedEvent(ByVal sender As Object, ByVal args As FileUploadCompletedEventArgs)
Public Class FileUploadCompletedEventArgs
    Private m_fileName As String
    Public Property FileName() As String
        Get
            Return m_fileName
        End Get
        Set(ByVal value As String)
            m_fileName = value
        End Set
    End Property
    Private m_filePath As String
    Public Property FilePath() As String
        Get
            Return m_filePath
        End Get
        Set(ByVal value As String)
            m_filePath = value
        End Set
    End Property

    Public Sub New()
    End Sub

    Public Sub New(ByVal fileName__1 As String, ByVal filePath__2 As String)
        FileName = fileName__1
        FilePath = filePath__2
    End Sub
End Class

Public Class FileUploadProcess
    Public Event FileUploadCompleted As FileUploadCompletedEvent
    ''' <summary> 
    ''' Determines if uploaded files should be renamed according to the user uploading them, otherwise if 
    ''' multiple users upload a file of the same name, it would try to save the file to the same name, throwing an error. 
    ''' Another way to prevent this is to create a seperate folder for each file. 
    ''' </summary> 
    Private m_uniqueUserUpload As Boolean
    Public Property UniqueUserUpload() As Boolean
        Get
            Return m_uniqueUserUpload
        End Get
        Set(ByVal value As Boolean)
            m_uniqueUserUpload = value
        End Set
    End Property

    Public Sub New()
    End Sub

    Public Sub ProcessRequest(ByVal context As HttpContext, ByVal uploadPath As String)
        Dim filename As String = context.Request.QueryString("filename")
        Dim complete As Boolean
        If String.IsNullOrEmpty(context.Request.QueryString("Complete")) Then complete = True Else complete = Boolean.Parse(context.Request.QueryString("Complete"))
        Dim getBytes As Boolean
        If String.IsNullOrEmpty(context.Request.QueryString("GetBytes")) Then getBytes = False Else getBytes = Boolean.Parse(context.Request.QueryString("GetBytes"))
        Dim startByte As Long
        If String.IsNullOrEmpty(context.Request.QueryString("StartByte")) Then startByte = 0 Else startByte = Long.Parse(context.Request.QueryString("StartByte"))

        Dim filePath As String
        If UniqueUserUpload Then
            If context.User.Identity.IsAuthenticated Then
                filePath = Path.Combine(uploadPath, String.Format("{0}_{1}", context.User.Identity.Name.Replace("\", ""), filename))
            Else
                If context.Session("fileUploadUser") Is Nothing Then
                    context.Session("fileUploadUser") = Guid.NewGuid()
                End If
                filePath = Path.Combine(uploadPath, String.Format("{0}_{1}", context.Session("fileUploadUser"), filename))
            End If
        Else
            filePath = Path.Combine(uploadPath, filename)
        End If
        Logging.DebugLog(filePath)

        If getBytes Then
            Dim fi As New FileInfo(filePath)
            If Not fi.Exists Then
                context.Response.Write("0")
            Else
                context.Response.Write(fi.Length.ToString())
            End If

            context.Response.Flush()
            Exit Sub
        Else

            If startByte > 0 AndAlso File.Exists(filePath) Then

                Using fs As FileStream = File.Open(filePath, FileMode.Append)
                    SaveFile(context.Request.InputStream, fs)
                    fs.Close()
                End Using
            Else
                Using fs As FileStream = File.Create(filePath)
                    SaveFile(context.Request.InputStream, fs)
                    fs.Close()
                End Using
            End If
            If complete Then
                If FileUploadCompletedEvent IsNot Nothing Then
                    Dim args As New FileUploadCompletedEventArgs(filename, filePath)
                    FileUploadCompletedEvent(Me, args)
                End If
            End If
        End If
    End Sub
    Private Sub SaveFile(ByVal stream As Stream, ByVal fs As FileStream)
        Dim buffer As Byte() = New Byte(4095) {}
        Dim bytesRead As Integer
        While (InlineAssignHelper(bytesRead, stream.Read(buffer, 0, buffer.Length))) <> 0
            fs.Write(buffer, 0, bytesRead)
        End While
    End Sub
    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
        target = value
        Return value
    End Function
End Class